package com.atguigu.gmall.pms.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.pms.config.OssProperties;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@RestController
@RequestMapping("/pms/oss")
@EnableConfigurationProperties(OssProperties.class)
public class OssController {
    //http://api.gmall.com/pms/oss/policy
    @Autowired
    OssProperties ossProperties;
    /*
        get和post请求报文的区别：
            post比get略安全
            1、post有请求体 get没有
                post可以上传文件
            2、post请求头多了请求体内容配置参数
        文件上传：
            1、之前的项目文件上传：请求方式必须是post
                前端将上传的文件提交给后端服务器
                后端服务器将文件上传到阿里云oss
            2、文件上传的最佳实现
                之前的方式：安全，阿里云oss参数配置在服务器中、保存文件参数后端服务器来生成
                            性能非常差，文件先提交给服务器在推送到阿里云oss
                改进：可以前端直传
                            不安全：oss的参数会配置到前端，容易丢失
                            性能非常高：用户直传，后端服务器不用处理文件的上传
                 最佳实现：
                        oss参数保存在后端服务器
                        前端js上传文件之前先访问后端接口获取临时授权
                        js在临时授权过期前上传文件 可以成功
     */


    // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
    String accessId;
    String accessKey;
    // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
    String endpoint;
    // 填写Bucket名称，例如examplebucket。
    String bucket;
    // 填写Host地址，格式为https://bucketname.endpoint。  我们在阿里云oss创建的桶 它会为我们分配一个子域名
    String host;


    @PostConstruct  //jdk提供的 在bean的构造器调用后立即执行的初始化方法
    public void init(){
        accessId = ossProperties.getAccessId();
        accessKey = ossProperties.getAccessKey();
        endpoint = ossProperties.getEndpoint();
        bucket = ossProperties.getBucket();
        host = ossProperties.getSchema()+bucket+"."+endpoint;
    }

    @GetMapping("policy")
    public ResponseVo policy() throws UnsupportedEncodingException {
        // 设置上传到OSS文件的前缀，可置空此项。置空后，文件将上传至Bucket的根目录下。
        String dir = new DateTime().toString("yyyy-MM-dd/");
        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        long expireTime = 30;
        //代表 获取的授权token的过期时间  ：  300s
        long expireEndTime = System.currentTimeMillis() + expireTime * 10000;
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyConds = new PolicyConditions();
        policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
        policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

        String postPolicy = client.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = client.calculatePostSignature(postPolicy);

        Map<String, String> respMap = new LinkedHashMap<String, String>();
        respMap.put("accessid", accessId);
        respMap.put("policy", encodedPolicy);
        respMap.put("signature", postSignature);
        respMap.put("dir", dir);
        respMap.put("host", host);
        respMap.put("expire", String.valueOf(expireEndTime / 1000));
        return ResponseVo.ok(respMap);
    }
}
